//
// RPC Remote Process Call
//

#ifndef __RPC_HXX__
#define __RPC_HXX__

#ifdef __cplusplus
extern "C" {
#endif


enum PARA_DIR{PARA_DIR_IN=(1<<0), PARA_DIR_OUT=(1<<1), PARA_DIR_IN_OUT=(PARA_DIR_IN|PARA_DIR_OUT)};
enum PARA_TYPE{PARA_TYPE_VAL, PARA_TYPE_PTR};

typedef struct
{
	BYTE dir;
	BYTE type;
	WORD len;

	DWORD para;
}ParaInfo;


DWORD _cdecl CallFunV(DWORD dwFnAddr, DWORD dwParaDwNumb, ...);
DWORD _cdecl CallFun(DWORD dwFnAddr, DWORD dwParaDwNumb, DWORD* pdwParaS);



//
//==== implements ====
//
#if (defined(RPC_IMP)|defined(KEN_LIB_IMP))

DWORD _cdecl CallFunV(DWORD dwFnAddr, DWORD dwParaDwNumb, ...)
{
	DWORD dwParaS[9];
	DWORD i;
	va_list arglist;

	
	va_start(arglist, dwParaDwNumb);
	for(i=0; i<dwParaDwNumb; i++)
	{
		dwParaS[i]=va_arg(arglist, DWORD);	// para
	}
    va_end(arglist);

	switch (dwParaDwNumb)
	{
	case 0:
		return (*((DWORD (*)())(dwFnAddr)))();

	case 1:
		return (*((DWORD (*)(DWORD))(dwFnAddr)))(dwParaS[0]);

	case 2:
		return (*((DWORD (*)(DWORD, DWORD))(dwFnAddr)))(dwParaS[0], dwParaS[1]);

	case 3:
		return (*((DWORD (*)(DWORD, DWORD, DWORD))(dwFnAddr)))(dwParaS[0], dwParaS[1], dwParaS[2]);

	case 4:
		return (*((DWORD (*)(DWORD, DWORD, DWORD, DWORD))(dwFnAddr)))(dwParaS[0], dwParaS[1], dwParaS[2], dwParaS[3]);

	case 5:
		return (*((DWORD (*)(DWORD, DWORD, DWORD, DWORD, DWORD))(dwFnAddr)))(dwParaS[0], dwParaS[1], dwParaS[2], dwParaS[3], dwParaS[4]);

	case 6:
		return (*((DWORD (*)(DWORD, DWORD, DWORD, DWORD, DWORD, DWORD))(dwFnAddr)))(dwParaS[0], dwParaS[1], dwParaS[2], dwParaS[3], dwParaS[4], dwParaS[5]);

	case 7:
		return (*((DWORD (*)(DWORD, DWORD, DWORD, DWORD, DWORD, DWORD))(dwFnAddr)))(dwParaS[0], dwParaS[1], dwParaS[2], dwParaS[3], dwParaS[4], dwParaS[5], dwParaS[6]);

	case 8:
		return (*((DWORD (*)(DWORD, DWORD, DWORD, DWORD, DWORD, DWORD))(dwFnAddr)))(dwParaS[0], dwParaS[1], dwParaS[2], dwParaS[3], dwParaS[4], dwParaS[5], dwParaS[6], dwParaS[7]);

	case 9:
		return (*((DWORD (*)(DWORD, DWORD, DWORD, DWORD, DWORD, DWORD))(dwFnAddr)))(dwParaS[0], dwParaS[1], dwParaS[2], dwParaS[3], dwParaS[4], dwParaS[5], dwParaS[6], dwParaS[7], dwParaS[8]);

	// not implement, raise a exception
	default:
		return (*((DWORD (*)())(0)))();
	}
	
}

DWORD _cdecl CallFun(DWORD dwFnAddr, DWORD dwParaDwNumb, DWORD* pdwParaS)
{
	switch (dwParaDwNumb)
	{
	case 0:
		return (*((DWORD (*)())(dwFnAddr)))();

	case 1:
		return (*((DWORD (*)(DWORD))(dwFnAddr)))(pdwParaS[0]);

	case 2:
		return (*((DWORD (*)(DWORD, DWORD))(dwFnAddr)))(pdwParaS[0], pdwParaS[1]);

	case 3:
		return (*((DWORD (*)(DWORD, DWORD, DWORD))(dwFnAddr)))(pdwParaS[0], pdwParaS[1], pdwParaS[2]);

	case 4:
		return (*((DWORD (*)(DWORD, DWORD, DWORD, DWORD))(dwFnAddr)))(pdwParaS[0], pdwParaS[1], pdwParaS[2], pdwParaS[3]);

	case 5:
		return (*((DWORD (*)(DWORD, DWORD, DWORD, DWORD, DWORD))(dwFnAddr)))(pdwParaS[0], pdwParaS[1], pdwParaS[2], pdwParaS[3], pdwParaS[4]);

	case 6:
		return (*((DWORD (*)(DWORD, DWORD, DWORD, DWORD, DWORD, DWORD))(dwFnAddr)))(pdwParaS[0], pdwParaS[1], pdwParaS[2], pdwParaS[3], pdwParaS[4], pdwParaS[5]);

	case 7:
		return (*((DWORD (*)(DWORD, DWORD, DWORD, DWORD, DWORD, DWORD))(dwFnAddr)))(pdwParaS[0], pdwParaS[1], pdwParaS[2], pdwParaS[3], pdwParaS[4], pdwParaS[5], pdwParaS[6]);

	case 8:
		return (*((DWORD (*)(DWORD, DWORD, DWORD, DWORD, DWORD, DWORD))(dwFnAddr)))(pdwParaS[0], pdwParaS[1], pdwParaS[2], pdwParaS[3], pdwParaS[4], pdwParaS[5], pdwParaS[6], pdwParaS[7]);

	case 9:
		return (*((DWORD (*)(DWORD, DWORD, DWORD, DWORD, DWORD, DWORD))(dwFnAddr)))(pdwParaS[0], pdwParaS[1], pdwParaS[2], pdwParaS[3], pdwParaS[4], pdwParaS[5], pdwParaS[6], pdwParaS[7], pdwParaS[8]);

	// not implement, raise a exception
	default:
		return (*((DWORD (*)())(0)))();
	}
	
}

#endif	//#if (defined(RPC_IMP)|defined(KEN_LIB_IMP))


#ifdef __cplusplus
}
#endif

#endif	//#ifndef __RPC_HXX__
